enum Direction1 {
    Up = 1,
    Down,
    Left,
    Right
}

/**
 * 数字枚举可以被混入到 计算过的和常量成员（如下所示）。 简短地说，不带初始化器的枚举或者被放在第一的位置，或者被放在使用了数字常量或其它常量初始化了的枚举后面。 换句话说，下面的情况是不被允许的：
 */
function getSomeValue1() {
    return 2
}
enum E1 {
    A = getSomeValue1(),
    // B, // error! 'A' is not constant-initialized, so 'B' needs an initializer
}


// 字符串枚举
enum Direction {
    Up = "UP",
    Down = "DOWN",
    Left = "LEFT",
    Right = "RIGHT",
}


// 异构枚举
enum BooleanLikeHeterogeneousEnum {
    No = 0,
    Yes = "YES",
}

// 计算的和常量成员
enum E2 { X }

// 它不带有初始化器且它之前的枚举成员是一个 数字常量。 这种情况下，当前枚举成员的值为它上一个枚举成员的值加1。
enum E3 { X, Y, Z }

enum E4 {
    A = 1, B, C
}

// 枚举成员使用 常量枚举表达式初始化。 常数枚举表达式是TypeScript表达式的子集，它可以在编译阶段求值。 当一个表达式满足下面条件之一时，它就是一个常量枚举表达式
enum FileAccess {
    // constant members
    None,
    Read    = 1 << 1,
    Write   = 1 << 2,
    ReadWrite  = Read | Write,
    // computed member
    G = "123".length
}

// 运行时的枚举
function fXX(obj: { X: number }) {
    console.log(obj)
    return obj.X;
}

// Works, since 'E' has a property named 'X' which is a number.
console.log(fXX(E3));



// 反向映射
enum Enum5 {
    A
}
let ea = Enum5.A
let Ea = Enum5[ea]
console.log(ea,Ea)//0 A




// const枚举
const enum Enum6 {
    A = 1,
    B = A * 2
}
// console.log(Enum6) // Enum6 is not defined

// 常量枚举只能使用常量枚举表达式，并且不同于常规的枚举，它们在编译阶段会被删除。 常量枚举成员在使用的地方会被内联进来。 之所以可以这么做是因为，常量枚举不允许包含计算成员。
const enum Directions {
    Up,
    Down,
    Left,
    Right
}

let directions = [Directions.Up, Directions.Down, Directions.Left, Directions.Right]
//生成后的代码为：
//var directions = [0 /* Up */, 1 /* Down */, 2 /* Left */, 3 /* Right */];
console.log(directions)//[0, 1, 2, 3]



// 外部枚举
declare enum Enum7 {
    A = 1,
    B,
    C = 2
}
// console.log(Enum7.A) //Enum7 is not defined










